function AddressSelectorShow(data)
{
    var wrapper = document.address_selector;

    if (!wrapper)
        return;

    wrapper.data = data;

    // render
    var render1 = function(data)
    {
        // IE6 slow string fix
        var StringBuffer = function() { this.str = []; }
        StringBuffer.prototype =
        {
            append: function(str) { this.str[this.str.length] = str; },
            toString: function() { return this.str.join(''); }
        }

        var html = '';
        var buff = new StringBuffer();
        var splitter = wrapper.options.splitter;
        buff.append('<select size="2">');

        for (var i in data)
        {
            // name
            if (data[i][1] != '')
            {
                buff.append('<option value="');
                buff.append(i);
                buff.append('">');
                buff.append(data[i][2]);
                buff.append('</option>');
            }
            // splitter
            else
            {
                buff.append('<option disabled="disabled" value="">');
                buff.append(splitter);
                buff.append('</option>');
            }
        }
        buff.append('</select>');

        var select = buff.toString();

        // find prev level
        var level = 0;
        for(var x in wrapper.level_data)
        {
            level++;
        }
        if (level == 0)
            var back = '';
        else
            var back = '<a class="back"><span>← Назад</span></a>';
        var ok = '<a class="ok"><span>Готово</span></a>';
        var ok = '';
        var html = '<div><a class="close"><span></span></a>'+select+back+ok+'</div>';

        return html;
    }


    var render2 = function(data)
    {
        var show_letters = (data.length > 0 && data[0][0] == 2) ? true : false;
        if (data.length < 20)
        {
            var items1 = data;
            var items2 = [];
            var items3 = [];
            show_letters = false;
        }
        else
        {
            var portion = Math.round(data.length / 3);
            var items1 = data.slice(0, portion);
            var items2 = data.slice(portion, 2*portion);
            var items3 = data.slice(2*portion, data.length-1);
        }

        var column1_html = '';
        var column2_html = '';
        var column3_html = '';
        var data_idx = 0;

        // items
        var letter = '';

        for(var i in items1)
        {
	    if (typeof items1[i][2] != 'string')
		continue;

            var l = items1[i][2].substr(0, 1);
            if (show_letters && letter != l)
            {
                column1_html += '<b>'+l+'</b>';
                letter = l;
            }

            if (items1[i][1] == '')
                column1_html += '<hr>';
            else
            {
                if (items1[i][0] < 4)
                    column1_html += '<a class="link" href="#'+data_idx+'">'+items1[i][2]+' '+items1[i][3]+'</a>';
                else
                    column1_html += '<a class="link" href="#'+data_idx+'">'+items1[i][2]+'</a>';
            }
            data_idx++;
        }
        column1_html = '<div class="column column1">'+column1_html+'</div>';

        var letter = '';
        for(var i in items2)
        {
	    if (typeof items2[i][2] != 'string')
		continue;

            var l = items2[i][2].substr(0, 1);
            if (show_letters && letter != l)
            {
                column2_html += '<b>'+l+'</b>';
                letter = l;
            }
            if (items2[i][1] == '')
                column2_html += '<hr>';
            else
            {
                if (items2[i][0] < 4)
                    column2_html += '<a class="link" href="#'+data_idx+'">'+items2[i][2]+' '+items2[i][3]+'</a>';
                else
                    column2_html += '<a class="link" href="#'+data_idx+'">'+items2[i][2]+'</a>';
            }
            data_idx++;
        }
        column2_html = '<div class="column column2">'+column2_html+'</div>';

        var letter = '';
        for(var i in items3)
        {
	    if (typeof items3[i][2] != 'string')
		continue;

            var l = items3[i][2].substr(0, 1);
            if (show_letters && letter != l)
            {
                column3_html += '<b>'+l+'</b>';
                letter = l;
            }
            if (items3[i][1] == '')
                column3_html += '<hr>';
            else
            {
                if (items3[i][0] < 4)
                    column3_html += '<a class="link" href="#'+data_idx+'">'+items3[i][2]+' '+items3[i][3]+'</a>';
                else
                    column3_html += '<a class="link" href="#'+data_idx+'">'+items3[i][2]+'</a>';
            }
            data_idx++;
        }
        column3_html = '<div class="column column3">'+column3_html+'</div>';

        // find prev level
        var level = 0;
        for(var x in wrapper.level_data)
        {
            level++;
        }
        // buttons
        if (level == 0)
            var back = '<h2>Выбрерите регион</h2><a class="back" style="display:none;"><span>← Назад</span></a>';
        else
            var back = '<a class="back"><span>← Назад</span></a>';
        var ok = '<a class="ok"><span>Готово</span></a>';
        var ok = '';

        var html = '<div class="inner"><a class="close"><span></span></a>'+back+ok + '<div class="scroller">'+column1_html + column2_html + column3_html +'</div>'+ '</div>';

        return html;
    }


    var html = render2(data);

    // show
    //wrapper.innerHTML = html;
    var divs = wrapper.getElementsByTagName('DIV');
    for(var i=0; i<divs.length; i++)
        wrapper.removeChild(divs[i]);

    var div = document.createElement('DIV');
    wrapper.appendChild(div);
    div.innerHTML = html;


    /*
     * bind event
     */
    var bind = function(element, event, callback)
    {
        // DOM2: FF, Chrome, Opera
        if (element.addEventListener)
            element.addEventListener(event, callback, false);
         // IE 5+
        else if (element.attachEvent)
            element.attachEvent("on"+event, callback);
    }

    // bind 'click'
    var selects = wrapper.getElementsByTagName('SELECT');

    // select
    if (selects.length > 0)
    {
        var select = selects[0];
        bind(select, 'change', wrapper.onselect);
    }
    // a
    else
    {
        var aa = wrapper.getElementsByTagName('A');
        for(var a in aa)
        {
            if (aa[a] && aa[a].className == 'link')
                bind(aa[a], 'click', wrapper.onselect);
        }
    }

    var close = wrapper.getElementsByTagName('A')[0];
    bind(close, 'click', wrapper.closeSelector);

    if (back != '')
    {
        var back = wrapper.getElementsByTagName('A')[1];
        bind(back, 'click', wrapper.back);
    }
}




function AddressSelector(elements, _options)
{
    // init options
    var options =
        {
            level:    'city',   // level (region | subregion | city)
            popup_id: 'address-selector',   // dialog id
            onSelect: null, // callback function emitted on select item
            baseurl:  '/demo',
            scroll:  true,  // scroll to element
            focus:  true,   // focus element
            splitter: '·······································································································································'
        };

    for (var opt in _options)
        options[opt] = _options[opt];

    // level code
    var levels = ['stub', 'country', 'region', 'subregion', 'city'];
    var fields = ['level', 'code', 'name', 'socr', 'index', 'gninmb', 'okatd'];
    var path = ['/', '/', '/regions/', '/cities-all/'];
    var level_index = 0;
    options.level = options.level.toLowerCase();

    for(var i=0; i<levels.length; i++)
    {
        if (levels[i] == options.level)
        {
            level_index = i;
            break;
        }
    }

    // Get scroll position
    var getScroll = function()
    {
        var x = 0, y = 0;
        if( typeof( window.pageYOffset ) == 'number' ) {
            //Netscape compliant
            y = window.pageYOffset;
            x = window.pageXOffset;
        } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
            //DOM compliant
            y = document.body.scrollTop;
            x = document.body.scrollLeft;
        } else if( document.documentElement &&
        ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
            //IE6 standards compliant mode
            y = document.documentElement.scrollTop;
            x = document.documentElement.scrollLeft;
        }
        var obj = new Object();
        obj.x = x;
        obj.y = y;
        return obj;
    };

    // load page
    var loadPage = function(wrapper, url)
    {
        var script = document.createElement('script');
        script.src = options.baseurl+url;
        script.type = 'text/javascript';
        script.encoding = "UTF-8";
        wrapper.appendChild(script);
    }


    /*
     * Center element on page (with scrolling)
     */
    var centerElement = function(e)
    {
        var scroll = getScroll();
        e.style.top = scroll.y+10+'px';
    }


    /*
     * Clear old levels data
     */
    var clearLevels = function(wrapper, current_level_idx)
    {
        for(var i=current_level_idx+1; i<levels.length; i++)
            if (wrapper.data[levels[i]])
                delete wrapper.data[levels[i]];
    }


    /*
     * Get named object with data
     */
    var getNamedData = function(data)
    {
        var named={};

        for(var i=0; i<data.length; i++)
            named[fields[i]] = data[i];

        return named;
    }


    /*
     * Parse 'Region[name]' and return {level:Region, field:name}
     */
    var parseWhatNeed = function(what_need)
    {
        var splitted = what_need.split('.');
        return {level:splitted[0], field:splitted[1]}
    }


    /*
     * Create wrapper
     */
    var createWrapper = function()
    {
        if (document.address_selector)
            return document.address_selector;

        // find active element. for add div
/*
        if (this != window)
            var element = this;
        else if (this == window && window.event && window.event.target)
            var element = window.event.target;
        else if (this == window && window.event && window.event.srcElement)
            var element = window.event.srcElement;
        else

            var element = document.getElementsByTagName("body")[0]; // FF
*/
        var element = document.getElementsByTagName("BODY")[0]; // for all

        // wrapper
        var wrapper = document.createElement('div');
        wrapper.id = options.popup_id;
        element.appendChild(wrapper);

        // center wrapper
        centerElement(wrapper);
        document.address_selector = wrapper;

        // init data
        this.data = {};
        wrapper.data = {};
        wrapper.level_data = {};
        wrapper.elements = elements;
        wrapper.level_index = level_index;
        wrapper.options = options;

        /*
         * Close selector
         */
        wrapper.closeSelector = function()
        {
            wrapper.parentNode.removeChild(wrapper);
            document.address_selector = false;
        }


        /*
         * back
         */
        wrapper.back = function()
        {
            // find prev level
            var level = 0;
            for(var x in wrapper.level_data)
            {
                level++;
            }

            // restore data
            if (level == 1)
            {
                var code = 'regions';
            }
            else
            {
                var level_name = levels[level];
                var data = wrapper.level_data[level_name];
                var code = data.code;
            }

            // remove last saved data
            delete wrapper.level_data[levels[level+1]];

            // load
            var url = path[level] + code + '.js';
            loadPage(wrapper, url);
        }

        wrapper.onselect = function(evt)
        {
            if (!evt)
                var evt = window.event;

            // element 'select'
            var e = (evt.target) ? evt.target : evt.srcElement;

            // stop bubble
            evt.cancelBubble = true;

            if (evt.stopPropagation)
                evt.stopPropagation();

            if (evt.preventDefault)
                evt.preventDefault();

            evt.returnValue = false;

            // get data
            var value = e.value ? e.value : e.href.split('#')[1];
            var data = wrapper.data[value];
            var level = Number(data[0]);
            var level_index = wrapper.level_index;
            var code = data[1];

            // save level data (by level name)
            if (data)
            {
                var selected_level_index = level;
                clearLevels(wrapper, selected_level_index); // clear

                var level_name = levels[selected_level_index];
                wrapper.level_data[level_name] = getNamedData(data); // save
            }

            // it is required level
            if (data && level_index == level)
            {
                // scan all inputs
                for(var name in elements)
                {
                    // set input value
                    var found = document.getElementsByName(name);
                    var what_need = elements[name].toLowerCase();
                    var wn = parseWhatNeed(what_need);

                    // find element by name
                    for (var i=0; i<found.length; i++)
                    {
                        // input for set
                        element = found[i];

                        if (wrapper.level_data[wn.level])
                        {
                            //  set field value
                            var value = wrapper.level_data[wn.level][wn.field];
                            //value = decodeURIComponent(value);
                            element.value = value;
                            // scroll to element
                            if (options.scroll)
                            {
                                element.scrollIntoView(true);
                                var scroll = getScroll();
                                window.scrollTo(scroll.x, scroll.y-80);
                            }
                            if (options.focus)
                                element.focus();
                        }
                        else
                            element.value = '';
                    }
                }

                if (options.onSelect)
                {
                    options.onSelect(wrapper.level_data);
                }

                wrapper.closeSelector(wrapper);

                return false;
            }

            var url = path[level] + code + '.js';
            loadPage(wrapper, url);
        }


        // load first page
        loadPage(wrapper, "/regions.js");

        return wrapper;
    }

    // Show popup
    createWrapper();
}
